#pragma once


#include <iostream>
#include <memory>
#include <functional>
#include "Epoller.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Reactor.hpp"


using func_t = std::function<std::string(std::string&)>;


//定位: 只负责IO
class IOServer: public Connection
{
    static const int size = 1024;
public:
    IOServer(int sockfd)
    {
        SetNonBlock(sockfd);
        SetSockfd(sockfd);
        SetEvents(EPOLLIN|EPOLLET);
    }
    virtual void Recver() override
    {
        //UpdataTime();
        //1.读取所有数据
        while(true)//ET模式
        {
            char buffer[size];
            ssize_t s = recv(Sockfd(),buffer,sizeof(buffer)-1,0);//非阻塞,没有数据就返回-1
            if(s > 0)
            {
                //读取成功
                buffer[s] = 0;
                AppendString(buffer);
            }
            if(s == 0)
            {
                //对端关闭连接
                Excepter();
                return;
            }
            else
            {
                //没有数据读了
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    //发送错误了
                    Excepter();
                    return;
                }
            }
        }
        //本轮数据读取完了
        std::cout << "outbuffer: \n" << InString() << std::endl;
        //你能确定你读的消息是一个完整的报文吗? 不能!!!
        //所以要引入协议
        std::string result;
        if(_on_message)
            result = _on_message(InString());
        
        AppendToOut(result);
        //如何把outbuffer发送给对方
        if(!IsOutBufferEmpty())
        {
            //Sender(); // 方案1,直接发送
            //方案2,使能Writeable即可
            GetOwner()->EnableReadWrite(Sockfd(),true,true);
        }
            
    }
    virtual void Sender() override
    {
        //UpdataTime();
        while(true)
        {
            //实际发送的数据大小n
            ssize_t n = send(Sockfd(),OutString().c_str(),OutString().size(),0);
            if(n > 0)
            {
                //成功
                DisCardOutString(n);//移除n个
            }
            else if(n == 0)
            {
                //缓存区读完了
                break;
            }
            else
            {
                if(errno = EAGAIN || errno == EWOULDBLOCK)
                {
                    //缓存区写满了
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        //1. outbuffer  empty
        //2. 缓存区被写满了 && outbuffer还有数据,写条件不满足,使能sockfd在epoll中的事件
        if(!IsOutBufferEmpty())
        {
            //修改对sockfd的事件关心! --- 写事件
            GetOwner()->EnableReadWrite(Sockfd(),true,true);
        }
        else
        {
            GetOwner()->EnableReadWrite(Sockfd(),true,false);
        }
    }
    virtual void Excepter() override
    {
        //IO读取时,所有的异常处理,全部都会转化成读写
        //出异常,怎么做?
        //打印日志,差错处理,关闭连接,Reactor异常connection,从内核中,移除对fd的关心
        LOG(LogLevel::INFO) << "客户端连接可能结束,进行异常处理: " << Sockfd();
        GetOwner()->DelConnection(Sockfd());
    }
    void RegisterOnMessage(func_t on_message)
    {
        _on_message = on_message;
    }
    ~IOServer()
    {

    }
private:
    func_t _on_message;
};

